﻿using System;
using System.Collections.Generic;
using NodaTime.TimeZones;

namespace NodaTime
{
    /// <summary>
    /// Static access to date/time zone providers built into Noda Time. These are all thread-safe and caching.
    /// </summary>
    public static class DateTimeZoneProviders
    {
        private static readonly DateTimeZoneCache tzdbFactory = new DateTimeZoneCache(new TzdbDateTimeZoneSource("NodaTime.TimeZones.Tzdb"));
        private static readonly DateTimeZoneCache bclFactory = new DateTimeZoneCache(new BclDateTimeZoneSource());
        private static readonly DateTimeZoneCache ituFactory = new DateTimeZoneCache(new ItuDateTimeZoneSource());

        /// <summary>
        ///  Returns the IDs of all date/time zone providers available within Noda Time. The order of the keys is not guaranteed.
        /// </summary>
        public static IEnumerable<string> Ids { get { return IdToFactoryMap.Keys; } }

        private static readonly Dictionary<string, IDateTimeZoneProvider> IdToFactoryMap = new Dictionary<string, IDateTimeZoneProvider>
        {
            { tzdbFactory.Id, tzdbFactory },
            { bclFactory.Id, bclFactory },
            { ituFactory.Id, ituFactory }
        };
 

        /// <summary>
        /// Gets the default time zone provider, which is initialized from resources within the NodaTime assembly.
        /// </summary>
        /// <remarks>
        /// Currently this returns the same value as the <see cref="Tzdb"/> property.
        /// </remarks>
        public static IDateTimeZoneProvider Default { get { return Tzdb; } }

        /// <summary>
        /// Gets a time zone provider which uses the <see cref="TzdbDateTimeZoneSource"/>.
        /// </summary>
        public static IDateTimeZoneProvider Tzdb { get { return tzdbFactory; } }

        /// <summary>
        /// Gets a time zone provider which uses the <see cref="BclDateTimeZoneSource"/>.
        /// </summary>
        public static IDateTimeZoneProvider Bcl { get { return bclFactory; } }

        /// <summary>
        ///   Fetches a date/time zone provider by its unique identifier.
        /// </summary>
        /// <param name="id">The case-sensitive ID of the date time zone provider</param>
        /// <returns>The <see cref="IDateTimeZoneProvider"/> with the given ID.</returns>
        /// <seealso cref="IDateTimeZoneProvider.Id"/>
        /// <exception cref="TimeZoneNotFoundException">No date time zone provider for the specified ID can be found.</exception>
        public static IDateTimeZoneProvider ForId(string id)
        {
            IDateTimeZoneProvider provider;
            if (IdToFactoryMap.TryGetValue(id, out provider))
                return provider;

            throw new TimeZoneNotFoundException(string.Format("The time zone provider '{0}' does not exist.", id));
        }

    }
}
